<template>
  <!-- 头部区域 -->
  <home-head :today="state.today" />

  <!-- 轮播图 -->
  <section class="banner-box">
    <van-swipe :autoplay="3000" lazy-render v-if="state.swipeData.length > 0">
      <van-swipe-item v-for="item in state.swipeData" :key="item.id">
        <router-link :to="`/detail/${item.id}`">
          <img :src="item.image" alt="" class="pic" />
          <div class="desc">
            <h3 class="title">{{ item.title }}</h3>
            <p class="author">{{ item.hint }}</p>
          </div>
        </router-link>
      </van-swipe-item>
    </van-swipe>
  </section>

  <!-- 新闻列表 -->
  <van-skeleton
    title
    :row="5"
    v-if="state.newsList.length === 0"
  ></van-skeleton>
  <template v-else>
    <section
      class="news-box"
      v-for="(item, index) in state.newsList"
      :key="item.date"
    >
      <van-divider content-position="left" v-if="index > 0">
        {{ formatTime(item.date, "{1}-{2}") }}
      </van-divider>
      <div class="content">
        <news-item v-for="cur in item.stories" :key="cur.id" :data="cur" />
      </div>
    </section>
  </template>

  <!-- 加载更多 -->
  <div class="lazy-more" v-show="state.newsList.length > 0" ref="loadBox">
    <van-loading size="12px">小主，精彩数据准备中...</van-loading>
  </div>
</template>

<script>
export default {
  name: "Home",
};
</script>

<script setup>
import HomeHead from "../components/HomeHead.vue";
import NewsItem from "../components/NewsItem.vue";
import { reactive, onBeforeMount, onMounted, ref, onBeforeUnmount } from "vue";
import api from "../api";
import { formatTime } from "../assets/utils";

let state = reactive({
  today: formatTime(null, "{0}{1}{2}"), //没有从服务器获取之前，先绑定客户端的当前日期
  swipeData: [], //轮播图数据
  newsList: [], //新闻列表数据
});

// 第一次渲染组件之前:从服务器获取今日新闻&轮播图数据
onBeforeMount(async () => {
  let { date, top_stories, stories } = await api.queryNewsLatest();
  state.today = date;
  state.swipeData = Object.freeze(top_stories);
  state.newsList.push(
    Object.freeze({
      date,
      stories,
    })
  );
});

// 加载更多数据
let loadBox = ref(null),
  ob = null;
onMounted(() => {
  ob = new IntersectionObserver(async (changes) => {
    let { isIntersecting } = changes[0];
    if (isIntersecting) {
      // 出现在可视窗口:加载更多数据
      let { newsList } = state,
        lastItem = newsList[newsList.length - 1];
      let result = await api.queryNewsBefore(lastItem.date);
      state.newsList.push(Object.freeze(result));
    }
  });
  ob.observe(loadBox.value);
});
onBeforeUnmount(() => {
  // 组件释放前，手动清除监听器
  ob.unobserve(loadBox.value);
  ob = null;
});
</script>

<style lang="less" scoped>
.banner-box {
  box-sizing: border-box;
  height: 375px;
  background: #eee;
  overflow: hidden;

  .van-swipe {
    height: 100%;

    a {
      display: block;
      height: 100%;
    }

    .pic {
      display: block;
      width: 100%;
      height: 100%;
    }

    .desc {
      position: absolute;
      bottom: 0;
      left: 0;
      box-sizing: border-box;
      padding: 20px;
      width: 100%;
      background: rgba(0, 0, 0, 0.5);
      background: -webkit-linear-gradient(
        top,
        rgba(0, 0, 0, 0),
        rgba(0, 0, 0, 0.5)
      );

      .title {
        line-height: 25px;
        font-size: 20px;
        color: #fff;
      }

      .author {
        line-height: 30px;
        font-size: 14px;
        color: rgba(255, 255, 255, 0.7);
      }
    }
  }

  :deep(.van-swipe__indicators) {
    left: auto;
    right: 20px;
    transform: none;

    .van-swipe__indicator--active {
      background-color: #fff;
      width: 18px;
      border-radius: 3px;
    }
  }
}

.news-box {
  padding: 0 15px;

  .van-divider {
    margin: 5px 0;
    font-size: 12px;

    &:before {
      display: none;
    }
  }
}

.van-skeleton {
  padding: 30px 15px;
}

.lazy-more {
  display: flex;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
  padding: 0 10px;
  height: 50px;
  background: #f4f4f4;
}
</style>